home *** CD-ROM | disk | FTP | other *** search
- /* pe7ptb.c */
- /* include external declarations */
- #include "pe7inc.h"
-
- /*
- * g n x t f l
- *
- * Get next file in a file group
- *
- */
-
- gnxtfl()
- {
- if (filecount-- == 0)
- return (FALSE); /* If no more, fail */
- if (debug) printf("Gnxtfl 1: filelist = \"%s\"\n",*filelist);
- filnam = *(filelist++);
- return (TRUE);
- }
-
- /*
- * d o s t a t s
- *
- * Gather various statistics
- *
- */
- dostat(type)
- int type;
- {
- ULONG time();
- switch(type)
- {
- case 1: /* Init Overall totals */
- total.files = 0;
- total.fc = 0;
- total.pli = 0;
- total.plo = 0;
- total.cli = 0;
- total.clo = 0;
- total.time = 0;
- break;
- case 2: /* Init File totals */
- file.fc = 0;
- file.pli = 0;
- file.plo = 0;
- file.cli = 0;
- file.clo = 0;
- file.time = time();
- break;
- case 3: /* Accumulate Overall totals */
- file.time = time()-file.time;
- if (vflg)
- {
- printf("%d Bytes %d Seconds %d/%d Packets",
- file.fc, file.time, file.plo, file.pli);
- printf(" %d/%d Characters\n", file.clo, file.cli);
- }
- total.fc += file.fc;
- total.pli += file.pli;
- total.plo += file.plo;
- total.cli += file.cli;
- total.clo += file.clo;
- total.time += file.time;
- break;
- case 4: /* Count total files */
- total.files++;
- }
- }
- /*
- * d o p a r
- *
- * Set parity bit
- *
- */
-
- dopar(ch)
- TEXT ch;
- {
- TEXT a;
-
- a=ch;
- if (pflg) /* True = generate parity */
- {
- a &= 0177; /* Strip top bit */
- switch (pflg)
- {
- case 'o': /* Odd parity */
- a |= 0200; /* Set bit then do even */
- case 'e': /* Even parity */
- a = (a & 15) ^ ((a >> 4) & 15);
- a = (a & 3) ^ ((a >> 2) & 3);
- a = (a & 1) ^ ((a >> 1) & 1);
- a = ch & 0177 | (a << 7);
- case 's': /* Space parity */
- default: /* No parity */
- break;
- case 'm': /* Mark parity */
- a |= 0200;
- }
- }
- return (a);
- }
-
- /*
- * c h k c h a r
- *
- * Check range of input and return the character or FALSE
- *
- */
-
- TEXT chkchar(c)
- TEXT c;
- {
- return ((c < 33) || (c > 62 && c < 96) || (c > 126) ? FALSE : c);
- }
- /*
- * f l u s h i n p u t
- *
- * Dump all pending input to clear stacked up NACK's.
- * (Implemented only for Berkeley Unix at this time).
- *
- */
-
- flushinput() /* Null version for non-Berkeley Unix */
- {
- estty(ttyfd,&ttymode); /* This flushes the input buffer */
- }
-
- /*
- * Kermit printing routines:
- *
- * printmsg - like printf with "Kermit: " prepended
- * error - like printmsg if local kermit; sends a error packet if remote
- * prerrpkt - print contents of error packet received from remote host
- */
- /*
- * U s a g e
- *
- * Like printmsg but will exit after printing the message
- *
- */
-
- Usage(message,a1,a2,a3,a4,a5)
- TEXT *message;
- {
- TEXT
- cp[BUFSIZE];
- cpystr(&cp, "Kermit usage: ", message, "\n", NULL);
- printf(&cp, a1, a2, a3, a4, a5);
- if (ttyfd > 0)
- estty (ttyfd,&savemode); /* Restore the tty to what it was */
- exit(NO);
- }
- /*
- * p r i n t m s g
- *
- * Print message on standard output if not remote.
- *
- */
-
- printmsg(fmt, a1, a2, a3, a4, a5)
- TEXT *fmt;
- {
- TEXT cp[BUFSIZE];
- cpystr(&cp, "Kermit: ", fmt, "\n", NULL);
- printf(&cp, a1, a2, a3, a4, a5);
- }
- /*
- * e r r o r
- *
- * Print error message.
- *
- * If remote, send an error packet with the message.
- *
- */
-
- error(fmt, a1, a2, a3, a4, a5)
- TEXT *fmt;
- {
- TEXT cp[MAXPACKSIZ], msg[80]; /* Some arrays for the strings */
- int len; /* The length of these arrays */
-
- convert(&cp, fmt); /* Convert the format string */
- len = decode(msg, 80, &cp, a1, a2, a3, a4, a5);
- spack('E',n,len,msg); /* Send the error packet */
- return;
- }
- /*
- * c o n v e r t
- *
- * Convert the UNIX format string to an IDRIS format string
- *
- */
-
- convert(out, in)
- TEXT *out, *in;
- {
- TEXT t,
- *cpp;
-
- cpp = out; /* Init the buffer pointer */
-
- while ((t = *cpp++ = *in++) != NULL)
- if (t == '%')
- switch (t = *in++)
- {
- case 'c':
- *cpp++ = 'a';
- *cpp++ = 'c';
- break;
- case 'x':
- *cpp++ = 'h';
- case 'd':
- *cpp++ = 'i';
- break;
- case 's':
- *cpp++ = 'p';
- break;
- case '\0':
- --in;
- break;
- default:
- *cpp++ = t;
- }
- }
- /*
- * p r e r r p k t
- *
- * Print contents of error packet received from remote host.
- *
- */
-
- prerrpkt(msg)
- TEXT *msg;
- {
- putstr(STDERR,\
- "Kermit: Abort with error from remote host:\n",\
- " ",msg,"\n",NULL);
- return;
- }
- /*
- * p r i n t f
- *
- * Print formatted output. Convert from UNIX to IDRIS
- *
- */
-
- printf(msg, a1, a2, a3, a4, a5)
- TEXT *msg;
- {
- TEXT
- cp[MAXPACKSIZ]; /* Line pointer for the reformatted string */
-
- convert(&cp, msg); /* Convert the string */
- putfmt(&cp, a1, a2, a3, a4, a5);
- }
- /*
- * i n l i n e
- *
- * Input a line (up to break char) from communications line
- *
- */
- inline(data)
- TEXT *data;
- {
- TEXT t;
- int len, t1;
-
- t1 = tflg ? XON : MYEOL;
- len = 0;
- do
- {
- if (ioread(&t) <= 0)
- {
- data[len]=MYEOL;
- return(len);
- }
- else
- if (t)
- {
- if (t == SOH) /* Resync on SOH */
- len = 0;
- else
- data[len++] = t;
- }
- }
- while ((t != t1) && (len < MAXPACKSIZ));
-
- file.cli += len + 1;
- data[len] = '\0'; /* Terminate input string */
-
- if (tflg) /* Turn around flag on? */
- do
- if (ioread(&t) < 0) break;
- while (t != XON);
-
- return (len);
- }
- /*
- * i o r e a d
- *
- * Read a character from the i/o channel
- *
- */
-
- ioread(t)
- TEXT *t;
- {
- ULONG time_end,
- time();
- int result;
-
- if (timint > 0)
- {
- time_end = time() + timint;
- do
- if ((result = read(ttyfd, t, 1)) > 0) break;
- while (time_end >= time());
- }
- else
- result = read(ttyfd, t, 1);
- if (pflg)
- *t &= 0177; /* Handle parity */
- return (result);
- }
-
- /*
- * x f i l e
- *
- * Fetch file and send file header
- *
- */
-
- TEXT xfile()
- {
- TEXT filnam1[MAXFNAME]; /* A buffer for the file name */
- TEXT *newfilnam; /* A pointer into the filename */
- TEXT *cp; /* char pointer */
- int num, len; /* Packet number, length */
- ULONG time();
-
- if (numtry++ > MAXTRY) return ('A'); /* If too many tries, give up */
-
- if (fd == NULL) /* If not already open, */
- {
-
- /* cpystr(filnam1, filnam, NULL); /* */
- btobemp(filnam1, filnam, MAXFNAME);
- if (filnamcnv) /* Convert upper case to lower */
- for (cp = &filnam1; *cp != '\0'; cp++)
- *cp = tolower(*cp);
-
- newfilnam = cp = filnam;
-
- while (*cp != '\0') /* Strip leading directories */
- if (*cp++ == '/')
- newfilnam = cp;
- len = cp - newfilnam; /* Compute length of filename */
-
- if (debug) printf("Xfile 1: Opening %s for sending.\n",&filnam1);
- /* Open file to be sent */
- if ((fd = fopen(&pfio, filnam1, READ)) == NULL)
- { /* If bad file pointer, give up */
- error("Cannot open file %s",filnam);
- return ('C'); /* Go back to idle mode */
- }
-
- if (vflg)
- printmsg("Sending %s as %s", filnam1, newfilnam);
- }
- dostat(2);
- spack('F',n,len,newfilnam); /* Send an F packet */
- switch(rpack(&len,&num,recpkt)) /* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num<0 ? 63 : num);/* unless it's NAK for next packet */
- case 'Y':
- if (n != num) /* which is just like an ACK for */
- { /* Wrong packet number */
- case FALSE: /* Receive failure, stay in F state */
- nxi++;
- return (state);
- }
- nxtpkt();
- dostat(4);
- repeat_count = 0; /* Reset repeat character counter */
- empty[1-pknum] = 0; /* Make other buffer empty */
- if ((empty[pknum] = size[pknum] = bufill (packet[pknum])) != EOF)
- return ('E'); /* Switch to data state */
- return ('Z'); /* Must be end of file */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- default:
- return ('A'); /* Something else, just "abort" */
- }
- }
-
- /*
- * s d a t a
- *
- * Send File Data
- *
- */
-
- TEXT sdata()
- {
- int num, len; /* Packet number, length */
-
- if (numtry++ > MAXTRY) return ('A'); /* If too many tries, give up */
-
- /* If the packet has not been acked then do not fill it
- We may need to retransmit it again */
- spack('D',n,size[pknum],packet[pknum]); /* Send a D packet */
- if (!empty[1-pknum])
- empty[1-pknum] = size[1-pknum] = bufill(packet[1-pknum]);
- switch(rpack(&len,&num,recpkt)) /* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num<0 ? 63 : num);/* unless it's NAK for next packet */
- case 'Y':
- if (n != num) /* which is just like an ACK for */
- { /* Wrong packet number */
- case FALSE: /* Receive failure, stay in D */
- nxi++;
- return (state);
- }
- empty[pknum] = 0; /* Empty this buffer */
- nxtpkt();
- if (size[pknum] == EOF)
- return ('Z'); /* Send eof packet */
- return ('E'); /* Got data, stay in state E */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- default:
- return ('A'); /* Anything else, "abort" */
- }
- }
-
- /*
- * r d a t a
- *
- * Receive Data
- *
- */
-
- TEXT rdata()
- {
- int num, len; /* Packet number, length */
- ULONG time();
-
- if (numtry++ > MAXTRY) return ('A'); /* "abort" if too many tries */
-
- switch(rpack(&len,&num,recpkt)) /* Get packet */
- {
- case 'D': /* Got Data packet */
- if (num != n) /* Right packet? */
- {
- /* No */
- if (oldtry++ > MAXTRY) return ('A'); /* If too many tries, abort */
- if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */
- {
- /* Previous packet again? */
- spack('Y',num,0,0); /* Yes, re-ACK it */
- numtry = 0; /* Reset try counter */
- return (state); /* Don't write out data! */
- }
- else return ('A'); /* sorry, wrong number */
- }
- /* Got data with right packet number */
- spack('Y',n,0,0); /* Acknowledge the packet */
- bufemp(recpkt,len); /* Write the data to the file */
- oldtry = numtry; /* Reset the try counters */
- nxtpkt();
- return ('D'); /* Remain in data state */
-
- case 'F': /* Got a File Header */
- if (oldtry++ > MAXTRY)
- return ('A'); /* If too many tries, "abort" */
- if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */
- {
- /* It was the previous one */
- spack('Y',num,0,0);/* ACK it again */
- numtry = 0; /* Reset try counter */
- return (state); /* Stay in Data state */
- }
- else return ('A'); /* Not previous packet, "abort" */
-
- case 'Z': /* End-Of-File */
- if (num != n)
- return ('A'); /* Must have right packet number */
- spack('Y',n,0,0); /* OK, ACK it. */
- fclose(&pfio); /* Close the file */
- fd = NULL; /* Say the file is closed */
- nxtpkt();
- dostat(3);
- return ('F'); /* Go back to Receive File state */
-
- case FALSE: /* Didn't get packet */
- nxi++;
- spack('N',n,0,0); /* Return a NAK */
- return (state); /* Keep trying */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- default:
- return ('A'); /* Some other packet, "abort" */
- }
- }
-
- /*
- * s e o f
- *
- * Send End-Of-File.
- *
- */
-
- TEXT seof()
- {
- int num, len; /* Packet number, length */
- ULONG time();
-
- if (numtry++ > MAXTRY) return ('A'); /* If too many tries, "abort" */
-
- spack('Z',n,0,0); /* Send a 'Z' packet */
- switch(rpack(&len,&num,recpkt)) /* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num<0 ? 63 : num);/* unless it's NAK for next packet, */
- case 'Y':
- if (n != num) /* which is just like an ACK for */
- { /* Wrong packet number */
- case FALSE: /* Receive failure, stay in Z */
- nxi++;
- return (state);
- }
- nxtpkt();
- dostat(3);
- if (debug) printf("Seof 1: Closing input file %s\n",filnam);
- fclose(&pfio); /* Close the file */
- fd = NULL; /* Set flag indicating no file open */
-
- if (debug) printf("Seof 2: Looking for next file...\n");
- if (gnxtfl() == FALSE) /* No more files go? */
- return ('B'); /* if not, break, EOT, all done */
- if (debug) printf("Seof 3: New file is %s\n",filnam);
- return ('T'); /* More files, switch state to T */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- default:
- return ('A'); /* Something else, "abort" */
- }
- }
-
- /*
- * s b r e a k
- *
- * Send Break (EOT)
- *
- */
-
- TEXT sbreak()
- {
- int num, len; /* Packet number, length */
- ULONG time();
-
- if (numtry++ > MAXTRY) return ('A'); /* If too many tries "abort" */
-
- spack('B',n,0,0); /* Send a B packet */
- switch(rpack(&len,&num,recpkt)) /* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num<0 ? 63 : num);/* unless NAK for previous packet, */
- case 'Y':
- if (n != num) /* Which is just like an ACK for */
- { /* Wrong packet number */
- case FALSE: /* Receive failure, stay in B */
- nxi++;
- return (state);
- }
- nxtpkt();
- return ('C'); /* Switch state to Complete */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- default:
- return ('A'); /* Other, "abort" */
- }
- }
- /*
- * s f i n i s h
- *
- * Send Finish (LOGOUT)
- *
- */
-
- TEXT sfinish()
- {
- int num, len; /* Packet number, length */
-
- if (numtry++ > MAXTRY) return ('A'); /* If too many tries "abort" */
-
- spack('G',n,1,"F"); /* Send a GF packet */
- switch(rpack(&len,&num,recpkt)) /* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num<0 ? 63 : num);/* unless NAK for previous packet, */
- case 'Y':
- if (n != num) /* which is just like an ACK for */
- { /* Wrong packet number */
- case FALSE: /* Receive failure, stay in B */
- nxi++;
- return (state);
- }
- nxtpkt();
- return ('C'); /* Switch state to Complete */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- default:
- return ('A'); /* Other, "abort" */
- }
- }
-
- /*
- * KERMIT utilities.
- *
- */
-
- /*
- * s p a c k
- *
- * Send a Packet
- *
- */
-
- spack(type,num,len,data)
- TEXT type, *data;
- int num, len;
- {
- register int i; /* Character loop counter */
- register TEXT *bufp; /* Buffer pointer */
- TEXT buffer[100]; /* Packet buffer */
- TEXT temp[12]; /* A buffer for a status message */
- int checksum;
-
- data[len] = '\0'; /* Null-terminate data to print it */
- if (debug>1) /* Display outgoing packet */
- {
- printf("Spack 1: type: %c\n",type);
- printf(" num: %d\n",num);
- printf(" len: %d\n",len);
- if (len != 0)
- printf(" data: \"%s\"\n",data);
- }
-
- bufp = buffer; /* Set up buffer pointer */
- for (i=1; i<=pad; i++)
- write(ttyfd,&padchar,1); /* Issue any padding */
-
- *bufp++ = dopar(SOH); /* Packet marker, ASCII 1 (SOH) */
- /* Send character count and set up checksum */
- *bufp++ = dopar(tochar(len + chkt - '0' + 2));
- *bufp++ = dopar(tochar(num)); /* Packet number */
- *bufp++ = dopar(type); /* Packet type */
-
- for (i=0; i<len; i++) /* Loop for all data characters */
- *bufp++ = dopar(data[i]); /* Get a character */
- *bufp = '\0'; /* Mark end for block check */
- switch (chkt)
- {
- case '1':
- *bufp++ = dopar(tochar(chk1(buffer+1)));
- break;
- case '2':
- checksum = chk2(buffer+1);
- *bufp++ = dopar(tochar((checksum & 07700) >> 6));
- *bufp++ = dopar(tochar(checksum & 077));
- break;
- case '3':
- checksum = chk3(buffer+1);
- *bufp++ = dopar(tochar((checksum & 0170000) >> 12));
- *bufp++ = dopar(tochar((checksum & 07700) >> 6));
- *bufp++ = dopar(tochar(checksum & 077));
- break;
- }
-
- if (eol)
- *bufp++ = dopar(eol); /* Extra-packet line terminator */
- *bufp = '\0';
-
- i = bufp - buffer;
- write(ttyfd, buffer, i); /* Send the packet */
- file.plo++;
- file.clo += i;
-
- if (vflg)
- {
- if (nxi == nxs)
- write(STDERR,&temp,decode(&temp,12,"%5i/\r",nxo++));
- else
- write(STDERR,&temp,decode(&temp,12,"%5i/%5i\r",
- nxo++, nxs = nxi));
- }
- }
-
- /*
- * r p a c k
- *
- * Read a Packet
- *
- */
-
- rpack(len,num,data)
- int *len, *num; /* Packet length, number */
- TEXT *data; /* Packet data */
- {
- int chksum, i, j, len1, pbl;
- TEXT t, /* Current input character */
- type, /* Packet type */
- cchksum[4], /* Our (computed) checksum */
- rchksum[4], /* Checksum received from other host */
- rpacket[MAXPACKSIZ]; /* Receive packet */
-
- if(!(len1=inline(&rpacket))) return (FALSE);
-
- i = 0;
- if ((t = rpacket[i++]) == MYEOL) return (FALSE);
- *len = unchar(t); /* Character count */
-
- if ((t = rpacket[i++]) == MYEOL) return (FALSE);
- *num = unchar(t); /* Packet number */
-
- if ((type = rpacket[i++]) == MYEOL) return (FALSE);
-
- pbl = ((type == 'S') || (type == 'I')) ? 1 : type == 'N' ?
- *len - 2 : chkt - '0';
- *len -= pbl + 2; /* Data length */
-
- for (j=0; j < *len;) /* The data itself, if any */
- if ((data[j++] = rpacket[i++]) == MYEOL) return (FALSE);
- data[*len] = '\0'; /* Mark the end of the data */
-
- /* Fetch the checksum */
- cchksum[0] = '\0';
- cchksum[1] = '\0';
- cchksum[2] = '\0';
- cchksum[3] = '\0';
- rchksum[0] = '\0';
- rchksum[1] = '\0';
- rchksum[2] = '\0';
- rchksum[3] = '\0';
- for (j=0; j < pbl;) /* The checksum */
- {
- if ((rchksum[j++] = rpacket[i]) == MYEOL) return (FALSE);
- rpacket[i++] = '\0';
- }
-
- if (debug > 1) /* Display incoming packet */
- {
- printf("Rpack 2: type: %c\n",type);
- printf(" num: %d\n",*num);
- printf(" len: %d\n",*len);
- if (*len != 0)
- printf(" data: \"%s\"\n",data);
- }
- switch (pbl)
- {
- case 1:
- cchksum[0] = tochar(chk1(&rpacket));
- break;
- case 2:
- chksum = chk2(&rpacket);
- cchksum[0] = tochar((chksum & 07700) >> 6);
- cchksum[1] = tochar(chksum & 077);
- break;
- case 3:
- chksum = chk3(&rpacket);
- cchksum[0] = tochar((chksum & 0170000) >> 12);
- cchksum[1] = tochar((chksum & 07700) >> 6);
- cchksum[2] = tochar(chksum & 077);
- }
- if (!cmpstr(cchksum, rchksum))
- type = FALSE;
-
- file.pli++;
- flushinput();
- return (type); /* All OK, return packet type */
- }
-
- /*
- * n e x t p k
- *
- * Increment packet number to the next one. Reset retry counter.
- *
- */
-
- nxtpkt()
- {
- pknum = 1 & (n = (n+1)%64); /* Bump packet count */
- numtry = 0; /* Start a new counter */
- }
-
- /* pe7ptb.c End-of-file */
-